home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr49
/
105_01.zip
/
LIB.C
< prev
next >
Wrap
Text File
|
1993-06-09
|
17KB
|
660 lines
/*addmoney will add dollars and cents which are presented in an array
which is 6 unsigned integers. The first integer is the dollars of the
first number, the second integer the cents of the first number, the
third integer the dollars of the second number, and the fourth integer
the cents of the second number. The answer, which properly checks for
overflow of the cents, has the dollars in the fifth integer and cents in
the sixth integer. This routine will only add money, it will not subtract!
The maximum value permitted in the answer (and obviously in either of the
values is $65535.99. There are no error checks. */
addmoney(money)
unsigned money[];
{
money[4] = money[0] + money[2];
money[5] = money[1] + money[3];
if (money[5] > 99)
{
money[5] -= 100;
money[4]++;
}
return;
}
/* chkdate will check an ASCII string to see if it is a proper date. A
ptoper date is one which has a number of 1 to 31 followed by a correct
3-letter code. If an improper date is found, chkdate returns -1; else
it returns the day of year where JAN 1 is a 1 and every month has 31
days. */
chkdate(dd)
char dd[];
{
int i,j,k;
char dt[36];
k = atoi(dd);
if (k < 1 || k > 31)
return(-1);
i = 0;
while(isdigit(dd[i++]));
for (j=0,i--;j<3;j++,i++)
dd[i] = toupper(dd[i]);
i -=3;
movmem("JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC",dt,36);
for(j = 0; j < 36; j+=3)
if(dt[j]==dd[i]&&dt[j+1]==dd[i+1]&&dt[j+2]==dd[i+2])
return(((j/3)*31) + k);
return(-1);
}
/*comma checks a buffer (resbuf) at an index (j) for the nth comma (nbr).
If it encounters an end-of-line(CR) or slash it returns a -1. Else it
returns the index to the first character after the comma.*/
comma(resbuf,j,nbr)
char resbuf[];
int j;
int nbr;
{
int i;
for (i = 0; i < nbr; i++)
{
while (resbuf[j] != ',')
{
if (resbuf[j] == 13 || resbuf[j] == 92)
return(-1);
j++;
}
j++;
}
return(j);
}
/*count counts the number of characters in the buffer (resbuf) from the
index (j) up to either the first comma,first slash, first end-of-line (CR),
or end of buffer (control Z). It does not count blanks in the total. The
total number of characters is returned as an integer.*/
count(resbuf,j)
char resbuf[];
int j;
{
int i;
for(i=0;resbuf[j]!=','&&resbuf[j]>26&&resbuf[j]!=92;j++)
if(resbuf[j] != ' ')
i++;
return(i);
}
/*count1 counts the number of characters in the buffer (resbuf) from the
index (j) up to either the first comma,first slash, first end-of-line (CR),
or end of buffer (control Z). It counts blanks in the total. The total number
of characters is returned as an integer. */
count1(resbuf,j)
char resbuf[];
int j;
{
int i;
for (i=0;resbuf[j]!=','&&resbuf[j]>26&&resbuf[j]!=92;i++,j++);
return(i);
}
/*error will print the alarm in the array (ss) and then hang until any
character is typed on the console. there are no error conditions or exit
parameters*/
error(ss)
char ss[];
{
printf("%s",ss);
bdos(1);
}
/*findline will look for the first line of the buffer (resbuf) starting at the
index (j) which has a first character match with the character in flag. Since
findline first looks for the beginning of the nextline it is necessary to have
a special case for j in order to get the very first line. Therefore if j is
negative then the first character of the first line is also checked. If a match
is found then the index to the character which matches is returned, else a -1
is returned indicating no match found.*/
findline(resbuf,j,flag)
char resbuf[];
int j;
char flag;
{
if(j < 0)
if(resbuf[0] == flag)
return(0);
while((j = nextline(resbuf,j)) != -1)
if (toupper(resbuf[j]) == flag)
return(j);
return(j);
}
/*getal is a special function used to retrieve airline information from
the airline file. It matches the two characters in al against the first 2
characters of 32 byte groupings in the airline file. If it finds a match
it returns the 32 byte array in buf1 and a exit parameter of zero. If it
cannot find a match it returns -1.*/
getal(al,buf1,fd)
char al[];
char buf1[];
int fd;
{
int i,j;
for (i=0;;i++)
{
rwblk(fd,buf1,0,1,i);
for(j=0;j<128;j+=32)
{
if((buf1[j] =='Z')&&(buf1[j+1]=='Z'))
return(-1);
if((buf1[j]==al[0])&&(buf1[j+1]==al[1]))
{
for (i=0;i<32;i++,j++)
buf1[i] = buf1[j];
return(0);
}
}
}
}
/*getcit is a special routine which matches a set of 3-byte city codes (plus
a string-ending zero) against a file on disk. The city codes are in the
array city, and the number of entries is in count. The disk file has a
16-byte array for each city which is moved into buf2. If all the cities
are found then a zero is returned, else a -1 is returned*/
getcit(city,buf1,buf2,count,fd)
char city[];
char buf1[];
char buf2[];
int count;
int fd;
{
int i,j,k,m,n;
n = 0;
for (i=0;;i++)
{
rwblk(fd,buf1,0,1,i);
for(j=0;j<128;j+=16)
{
for (k=0;city[k] != 26;k+=4)
{
if(stgcmp("ZZZ",&buf1[j],3))
return(-1);
if(stgcmp(&city[k],&buf1[j],3))
{
movmem(&buf1[j],&buf2[k * 4],16);
n++;
if(n==count)
return(0);
}
}
}
}
}
/*getdate will retrieve the date from the MPM function TOD and tranlate it
into a set of ASCII characters in the array date. It checks to see if the
TOD function has ever been run and if not prints an alarm to the operator
and exits back to MPM. Else it returns the month as 2 digits followed by
the day as 2 digits, followed by the last 2 digits of year. getdate does
proper checks for leap year and different size months.*/
getdate(date)
char date[];
{
int temp[3];
int day_tab[2][13];
int i,j,k;
int leap;
int year;
int yearday;
int month;
int day;
bdos (155,temp);
if(temp[0] == 761)
{
printf("No TOD entered \n");
exit(0);
}
for (yearday = temp[0],year = 2;;)
{
if ((yearday - 365) < 0)
break;
yearday -= 365;
year++;
if ((yearday - 365) < 0)
break;
yearday -=365;
year++;
if ((yearday - 366) < 0)
break;
yearday -=366;
year++;
if ((yearday - 365) < 0)
break;
yearday -=365;
year++;
}
initw(day_tab,"0,31,28,31,30,31,30,31,31,30,31,30,31");
initw(&day_tab[1][0],"0,31,29,31,30,31,30,31,31,30,31,30,31");
leap = year%4 == 0;
for (i = 1;yearday > day_tab[leap][i];i++)
yearday -= day_tab[leap][i];
itoa2(i,&date[0]);
itoa2(yearday,&date[2]);
year += 76;
itoa2(year,&date[4]);
return;
}
/*itoa2 is a little function used by getdate to convert an integer which must
be between 0 and 99 to 2 ASCII characters*/
itoa2(n,s)
char s[2];
int n;
{
s[0] = n/10 + '0';
s[1] = n%10 + '0';
}
/*getfare is a specialized function used for computing base airline fares
from gross fares. It receives dollars and cents as 2 integers and divides
them by the fraction represented by DIVA and DIVB (currently 1.05). The
answer is output as ASCII characters in the array out1 with 4 digits of
dollars,a decimal point and 2 digits of cents. Leading zeroes are turned
into blanks.*/
#define DIVA 1050
#define DIVB 105
getfare(dollars,cents,out1)
int dollars;
int cents;
char out1[];
{
int i;
int out[7];
for(i=0;i<7;i++)
{
out[i] = dollars/DIVA;
dollars = dollars%DIVA;
dollars = dollars*10;
}
for (i=4;i<7;i++)
{
cents = cents*10;
out[i] = out[i] + (cents/DIVB);
cents = cents%DIVB;
}
out[6] += 5;
for(i=6;i>=0;i--)
if(out[i] > 9)
{
out[i] -= 10;
out[i-1]++;
}
for(i=0;out[i] == 0;i++)
out[i] +=47;
for(i=0;i<6;i++)
out1[i] = out[i] + 48;
out1[6] = out1[5];
out1[5] = out1[4];
out1[4] = '.';
}
/*getsec will get a sector or group of sectors from the file represented
by fdd. The file must previously have been opened and it must have been
initialized such that the number of sectors in the file are represented
by a single bit in the first 4 sectors of the file. Since the bit map
for allocation is already allocated itself the first 4 bits must be set
to 1 for this scheme to work. The function assumes that the file is 3568
sectors long (the size of the largest file in my computer system at
double density) so this constant should be adjusted when used on other
systems. The input parameters permit the allocation of either 1,2,or
4 sector sizes. This is controlled via opt where 1 = 1,2 = 2, and anything
else = 4. It is possible to allocate several groups of sectors and this
is controlled by nbr. Thus to allocate 15 2-sector groupings set nbr to
15 and opt to 2. All sectors are allocated on even boundaries. i.e the
first sector of a 4-sector allocation is always evenly divisible by itself
(After all 0 is the first sector) Because it is necessary to read the bit
map to allocate it is necessary to provide a 512-byte buffer for the getsec
function to use to input it from disk. Finally, the array addr will contain
a list of the sectors which have been allocated. If a multi-sector allocation
is requested then the first of the 2 or 4 sectors is provided. Notice you
cannot mix sector sizes in a single call to getsec. If you want to check the
out-of-sectors condition I suggest you set zeros in addr and check for an
answer of zero.*/
#define FILESIZE 446 /*3568/8*/
getsec(nbr,addr,fdd,opt,buf)
int nbr;
int addr[];
int fdd;
int opt;
char buf[];
{
int i,j,k;
char mask;
int count;
rwblk(fdd,buf,0,4,0);
k = 0;
for(i=0;i<FILESIZE;i++)
{
if(buf[i] == 0377)
continue;
if(opt <= 1)
{
mask = 0200;
count = 1;
}
else if(opt == 2)
{
mask = 0300;
count = 2;
}
else
{
mask = 0360;
count = 4;
}
for(j=0;j<8;j+=count)
{
if(((buf[i]<<(j))&mask) == 0)
{
addr[k++]=(i<<3) + (j);
buf[i] = buf[i] | (mask >> j);
if(k == nbr)
{
rwblk(fdd,buf,1,4,0);
return(0);
}
}
}
}
}
/*itoa is right out of the bible. I don't know why Leor never included it*/
itoa(n,s) /*convert n to chacracters in s */
char s[];
int n;
{
int i, sign;
if ((sign = n) < 0) /* record sign */
n = -n; /* make n positive */
i = 0;
do /* generate digits in reverse order */
{
s[i++] = n%10+'0'; /* get next digit */
}
while ((n /= 10) > 0); /*delete it */
if (sign < 0)
s[i++] = '-';
s[i] = '\0';
reverse(s);
}
/*lineemp will take a set of ASCII characters from a terminal buffer of
a size indicated by the integer size and called crtbuf, and compress them
into an ASCII buffer called resbuf which has CR LF and terminates with a
control Z. The terminal buffer is checked for blank lines from the back
end and they are completely eliminated. lineemp returns the index to the
control Z which provides the size of the disk buffer.*/
lineemp(resbuf,crtbuf,size)
char resbuf[];
char crtbuf[];
int size;
{
int i,j,k,m;
int lastline;
for (i = size-1;i>0;i--)
if(crtbuf[i] != ' ')
break;
lastline = i/80;
for(i = k = m = 0;i<=lastline;i++,k+=80)
{
for(j = 80;j>0;j--)
if(crtbuf[k+j-1] != ' ')
break;
movmem(&crtbuf[k],&resbuf[m],j);
m = m + j;
resbuf[m++] = 13;
resbuf[m++] = 10;
}
resbuf[m] = 26;
return(m);
}
/*linefull is the opposite of lineemp. It takes a typical text file from
disk and puts it into a terminal buffer,throwing out the CR and LF and
setting all unused characters to blanks. Caution! linefull cannot use
tabs.*/
linefull(resbuf,crtbuf)
char *resbuf;
char *crtbuf;
{
char *line;
char c;
line = crtbuf;
while((c = *resbuf++) != 26)
{
if(c == 13)
{
resbuf++;
crtbuf = line = line + 80;
continue;
}
*crtbuf++ = c;
}
}
/*list will output a buffer of characters to the list device using the CPM
BDOS 5 function. The number of characters is specified by nbr. This function
is necessary because some idiot at Digital Research required a $ to terminate
the printer output and therefore you can't print any buffers with a $ in
them*/
list(stadd,nbr)
char stadd[];
int nbr;
{
int i;
for ( i = 0; i < nbr; i++)
{
if (stadd[i] == '_')
stadd[i] = ' ';
bdos (5,stadd[i]);
}
}
/*nextline searches an ASCII buffer for the beginning of the next line. If
it finds at least one more line it exits with an integer pointing to the
first character of that line. Else it exits with a -1. j specifies the
offset into the buffer to start the search. */
nextline(resbuf,j)
char resbuf[];
int j;
{
while (resbuf[j] != 13)
{
if (resbuf[j] == 26)
return (-1);
j++;
}
j++;
if (resbuf[++j] == 26)
return (-1);
return(j);
}
/*percent will take the dollars in array money[0] and the cents in array
money[1], multiply it by the percent value in array money[2], and leave
the answer as unsigned integers with dollars in array money[3], and cents
in array money[4]. Proper rounding is used and cents are guaranteed to be
less then 100. Caution! Do not use with negative numbers. */
percent(money)
unsigned money[];
{
unsigned i,j;
i = money[0] * money[2];
j = money[1] * money[2];
j = j + 50;
j = j/100;
money[3] = i/100;
money[4] = (i%100) + j;
if (money[4] > 99)
{
money[4] -= 100;
money[3] ++;
}
return;
}
/*putcity will move 3 characters from array s1 and put them in array s2. It
will then add a zero to array s2*/
putcity(s1,s2)
char *s1;
char *s2;
{
int i;
for (i=0;i<3;i++)
*s2++ = *s1++;
*s2 = 0;
}
/*putsec is the opposite of getsec. It will release sectors back to the system.
It has similar options to getsec and like getsec it cannot mix options. If
putsec gets a sector number to release which is out of range or if the sector
to be released is not currently set it will exit with a -1 and display an
alarm on the terminal*/
putsec(nbr,addr,fdd,opt,buf)
int nbr;
int addr[];
int fdd;
int opt;
char buf[];
{
int i,j,k;
char mask;
rwblk(fdd,buf,0,4,0);
if(opt <= 1)
mask = 0200;
else if(opt == 2)
mask = 0300;
else
mask = 0360;
for(i=0;i < nbr;i++)
{
if(addr[i] < FILESIZE * 8)
{
j = addr[i] >> 3;
k = addr[i] & 7;
if(((buf[j] << k) & mask) == mask)
{
buf[j] =buf[j] & ~(mask >> k);
continue;
}
}
printf("release err\n");
i = -1;
break;
}
rwblk(fdd,buf,1,4,0);
return(i);
}
/*reverse is another routine from the bible*/
reverse(s) /*reverse string s in place */
char s[];
{
int c,i,j;
for(i=0,j=strlen(s)-1;i<j;i++,j--)
{
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
/*rwblk combines read,write,and seek into one function. If you tend to use
seek + read or seek + write a lot it will save you space. The parameters
are fdd - the file descriptor, buf - the data buffer to read or write from,
rw - read/write flag 0 = read, nbc - number of sectors, sbc - starting
sector.*/
rwblk(fdd,buf,rw,nbc,sbc)
int fdd;
char buf[];
int rw;
int nbc;
int sbc;
{
int i;
if((i == seek(fdd,sbc,0)) != -1)
if(rw == 0)
while((i = read(fdd,buf,nbc)) != -1)
return(i);
else
while((i = write(fdd,buf,nbc)) != -1)
return(i);
printf("disk error");
return(i);
}
/*stgcmp is similar to strcmp. It does not require a zero to end the
string. Instead it has a character count as the parameter nbr. stgcmp
will compare upper and lower case characters as equals and does not do
an arithmetic comparison. The exit parameter is either 1 (TRUE) for
compare or zero (FALSE) for no compare.*/
stgcmp(rr,ss,nbr)
char rr[];
char ss[];
int nbr;
{
int i;
for(i = 0;i < nbr; i++)
if(toupper(rr[i]) != toupper(ss[i]))
return(0);
return(1);
}
/*submoney is identical to admoney except it subtracts rather than adds.
Since the money in array money[0] and money[1] is subtracted from the
money in array money[2] and array money[3] it is very important to make
sure that array money[2] and money[3] are larger than array money[0] and
money[1]. Array money[4] contains the dollar answer and array money[5]
contains the cents answer. */
submoney(money)
unsigned money[];
{
money[4] = money[2] - money[0];
if (money[3] < money[1])
{
money[3] +=100;
money[4]--;
}
money[5] = money[3] - money[1];
return(0);
}